import doT from 'doT';

let configuration = {
	// 是否不做缓存，开发阶段设置为true方便调试
	noCache: false,
	// 设置别名，会在某些地方用到
	alias: {},
	// 是否忽略异常
	ignoreError: false,
	// 用于hash route的配置，当hash变化时，触发的事件，你需要做的是返回一个jqueryDom对象，用于渲染页面
	// 如果不返回jquery Dom对象则不做渲染处理
	getHashChangeRenderDom: function(){},
	// 模板规则配置，需要配置模板初始化(init)、预渲染(beforeMount)、渲染(mounted)三部分操作
	// 默认使用的是doT模板引擎，此配置是用于扩展更多自定义的组件/模板解析逻辑，例如你可以集成vue。
	// 在template中除了init方法外，this对象都是组件生命周期方法中会得到的this对象。你可以对其进行扩展或值的读取
	template: {
		/**
		 * 初始化模板html，这是在第一次获取到模板html的时候进行的处理操作。
		 * 你可以预处理一些html，例如doT可以对模板进行编译缓存。或也可以不进行任何处理
		 * @param {Object} templateHtml 模板html，一定不是null
		 * @return 返回初始化之后的对象，如果无需进行初始化，可不返回或返回templateHtml，返回结果会传递给preRender
		 */
		init(templateHtml) {
			// 这是doT模板引擎的处理操作
			return doT.template(templateHtml);
		},
		/**
		 * 模板解析对象构造，而后将这个对象返回。
		 * 例如doT可以是执行解析后html，vue可以使new Vue。
		 * 总之这一步你需要对模板进行处理，但不在页面渲染。
		 * 返回结果将会交给render方法。
		 * 
		 * @param {Object} initReturnObj init方法中的返回参数，如果init方法没有返回任何值，则是templateHTML
		 * @param {Object} data 模板中的data部分的数据
		 * @return 返回一个模板解析后的对象，render和beforeMount方法中将会拿到这个对象
		 */
		preRender(initReturnObj,data) {
			// 这是doT模板引擎的处理操作
			return initReturnObj(data);
		},
		/**
		 * 渲染处理，将dom最终展示到页面上的操作
		 * 
		 * @param {Object} preRenderObject preRender方法的返回对象
		 * @param {Object} dom HtmlElement对象
		 * @param {Object} jqDom jqueryDom对象
		 */
		render(preRenderObject,dom,jqDom) {
			// 这是doT模板引擎的处理操作
			let $doms = $('<div/>').append($.parseHTML(preRenderObject, false)).children();
			jqDom.empty().append($doms);
		},
		/**
		 * 所有处理完毕，在准备执行mounted拦截器之前，要做的事情。
		 * @param {Object} preRenderObject preRender方法的返回对象
		 */
		beforeMount(preRenderObject){}
	},
};

export var globalConfig = configuration;

/**
 * 覆盖默认配置，传递一个object覆盖默认配置
 * 或返回配置信息，不传参数则返回当前配置
 * @param {Object} cfg 配置对象
 * @return 如果不传参数，则返回当前配置信息
 */
export function config(cfg){
	if (arguments.length === 0) return configuration ;
	if (!cfg) return ;
	for (var x in configuration) {
		if (cfg[x] != null) {
			configuration[x] = cfg[x];
		}
	}
}
/**
 * 替换一个字符串的前缀别名
 * @param {Object} str 要替换的字符串
 * @return 返回替换结束后的字符串
 */
export function replacePrefix(str){
	if (!str) return str ;
	if ('string' !== str) {
		str += '';
	}
	let maxPrefixLength = 0,aliasValue;
	for (let x in configuration.alias) {
		let i = str.indexOf(x);
		if (i === 0 && x.length > maxPrefixLength) {
			maxPrefixLength = x.length;
			aliasValue = configuration.alias[x];
		}
	}
	return maxPrefixLength ? aliasValue + str.substr(maxPrefixLength) : str ;
}

/**
 * 输出一个错误，如果ignoreError设置为true，则不作任何事情
 * @param {Object} message 要输出的信息
 */
export function error(message) {
	if (configuration.ignoreError) {
		return ;
	} else {
		throw message ;
	}
}

/**
 * 是否禁用缓存
 */
export function isNoCache(){
	return configuration.noCache;
}